package annotation;

import annotation.base.Constraints;
import annotation.base.DBTable;
import annotation.base.SQLInteger;
import annotation.base.SQLString;
import framework.AbstractTest;
import utils.Log;
import utils.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by shane on 2018/5/31.
 */
public class TableCreator extends AbstractTest {
    private static final String TAG = "TableCreator";

    @Override
    public void test(String[] args) {
        super.test(args);

        if (args.length < 1) {
            Log.vn("arguments annotated classes");
            return;
        }

        try {
            for (String className : args) {
                Class<?> cl = Class.forName(className);
                DBTable dbTable = cl.getAnnotation(DBTable.class);
                if (dbTable == null) {
                    Log.vn("No DBTable in class " + className);
                    continue;
                }


                String tableName = dbTable.name();
                // if the name is empty, user the class name
                if (StringUtils.isEmpty(tableName)) {
                    tableName = cl.getName().toUpperCase();
                }

                List<String> columnDefs = new ArrayList<>();

                for (Field field : cl.getDeclaredFields()) {
                    String columnName = null;
                    Annotation[] anns = field.getAnnotations();
                    if (anns == null || anns.length < 1) {
                        continue;
                    }

                    if (anns[0] instanceof SQLInteger) {
                        SQLInteger sqlInteger = (SQLInteger) anns[0];
                        // use field name if name not specified
                        if (sqlInteger.name().isEmpty()) {
                            columnName = field.getName().toUpperCase();
                        } else {
                            columnName = sqlInteger.name();
                        }

                        columnDefs.add(columnName + " INT" + getConstraints(sqlInteger.constraints()));
                    } else if (anns[0] instanceof SQLString) {
                        SQLString sqlString = (SQLString) anns[0];
                        // use field name if name not specified
                        if (sqlString.name().isEmpty()) {
                            columnName = field.getName().toUpperCase();
                        } else {
                            columnName = sqlString.name();
                        }

                        columnDefs.add(columnName + " VARCHAR(" + sqlString.value() + ")" + getConstraints(sqlString.constraints()));
                    }
                }


                StringBuilder sb = new StringBuilder();
                sb.append("CREATE TABLE ");
                sb.append(tableName);
                sb.append("(");

                for (String columnDef : columnDefs) {
                    sb.append("\n   ");
                    sb.append(columnDef);
                    sb.append(",");
                }

                String tableSql = sb.substring(0, sb.length()-1) + ");";
                Log.vn("Table CREATION SQL FOR " + className + " is:\n" + tableSql);
            }
        } catch (ClassNotFoundException cnf) {
            cnf.printStackTrace();
        } catch (Exception e) {

        }

    }

    private String getConstraints(Constraints con) {
        StringBuilder sb = new StringBuilder();

        if (!con.allowNull()) {
            sb.append(" NOT NULL ");
        }

        if (con.primaryKey()) {
            sb.append(" PRIMARY KEY");
        }

        if (con.unique()) {
            sb.append(" UNIQUE");
        }

        return sb.toString();

    }
}
